#!/usr/bin/env python
# -*-  coding: utf-8 -*-
#   
#   Copyright © 2008, 2009, 2010 Jan Svec <honza.svec@gmail.com> and Filip Jurcicek <filip.jurcicek@gmail.com>
#   
#   This file is part of Gmail Backup.
#
#   Gmail Backup is free software: you can redistribute it and/or modify it
#   under the terms of the GNU General Public License as published by the Free
#   Software Foundation, either version 3 of the License, or (at your option)
#   any later version.
#
#   Gmail Backup is distributed in the hope that it will be useful, but WITHOUT
#   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
#   more details.
#
#   You should have received a copy of the GNU General Public License along
#   with Gmail Backup.  If not, see <http://www.gnu.org/licenses/
#
#   See LICENSE file for license details
#
#   With changes by Jesper Hertel <jesper.hertel@gmail.com> (JH).

import collections
import os
import sys
import errno
import pickle

_submoduleListForVersioning = []
import versioning; _revisionInfo = versioning.getRevisionInfoFromTagsAndSubModules('$Revision: 134 $', '$Date: 2013-11-27 22:48:35 +0000 (Wed, 27 Nov 2013) $', _submoduleListForVersioning)


def getEmptySettings():
    # in this dictionary we store all settings
    emptySettings = collections.defaultdict(str)
    return emptySettings  

def getSettingsFilename():
    '''Generate a platform dependent configuration file name.'''

    directoryOfRunningPythonFile = os.path.dirname(sys.argv[0])
    gmailBackupGuiCfgFilename = os.path.join(directoryOfRunningPythonFile, 'gmail-backup-gui.cfg')
    if os.path.isfile(gmailBackupGuiCfgFilename):
        # The file with the name gmailBackupGuiCfgFilename exists. Use that.
        # JH: Is this some legacy support?
        settingsFilename = gmailBackupGuiCfgFilename
    else:
        # The file with the name gmailBackupGuiCfgFilename does not exist. 
        # Use another file placed somewhere in the user's home directory, using a 
        # standard way for the current operating system.
        
        # Get name of folder to place settings file in.
        if os.name == 'nt':
            # Windows. 
            # Use the "%APPDATA%\Gmail Backup" directory for the settings.
            # Settings should be placed in the Application Data folder for the
            # current user.
            appdata = os.environ['APPDATA']
            settingsFolderName = os.path.join(appdata, 'Gmail Backup')
        else:
            # Not Windows.
            # Use the ~/.gmb directory for the settings.
            settingsFolderName = os.path.expanduser(os.path.join('~', '.gmb'))
        
        # Now get the complete filename for the settings file.
        settingsFilename = os.path.join(settingsFolderName, 'settings')

    return settingsFilename


def _createFullDirectoryPath(directoryPath):
    '''
    Create the given directory including all missing parent 
    directories, if the directory does not exist.
    
    If the directory exists, do nothing.

    This corresponds to the Unix command 'mkdir -p directoryPath'.
    '''
    
    # Implementation from 
    # http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python
    # See discussion there why we use exception handling and
    # not just a simple test first of whether the directory exists.
    try:
        os.makedirs(directoryPath)
    except OSError as exception: # Python >2.5
        if exception.errno == errno.EEXIST and os.path.isdir(directoryPath):
            # Directory already exists. This is perfectly okay.
            pass
        else: 
            raise

def _createFullDirectoryPathForFile(filePath):
    '''
    Create the full directory path for the given filePath,
    if one or more of the directories in the path does not
    exist.
    
    If the full directory path exists, do nothing.

    This corresponds to the Unix command 'mkdir -p directoryPath'.
    '''
    directoryPath = os.path.dirname(filePath)
    _createFullDirectoryPath(directoryPath)


def saveSettingsToFile(settings):
    """Save the settings dictionary using pickle module."""    
    
    settingsFilename = getSettingsFilename()
    _createFullDirectoryPathForFile(settingsFilename)
    with open(settingsFilename, "wb") as settingsFileHandle:
        pickle.dump(settings, settingsFileHandle)
    

def _removeAllOtherKeysThan(dictionary, keyList):
    '''
    Return a copy of dictionary but only with the keys in keyList.
    
    :param dictionary:
    :param keyList:
    '''

    # Could probably be made as a clever pythonic one-liner, but it is not important.
    newDictionary = {}
    for key, value in dictionary.iteritems():
        if key in keyList:
            newDictionary[key] = value
    return newDictionary


def _applyToAllValuesInDictionary(dictionary, function):
    '''
    Return a copy of the given dictionary but with the given 
    function applied to all the values.
    
    :param dictionary:
        The original dictionary.
    :param function:
        Function to apply to all the values in dictionary.
    '''
    return dict((key, function(value)) for (key, value) in dictionary.iteritems())
    
    
def _cleanSettings(settingsDictionary):
    ALL_SETTINGS_KEYS = ["before", "folder", "login", "onlyNewest", "since"]
    settingsDictionary1 = _removeAllOtherKeysThan(settingsDictionary, ALL_SETTINGS_KEYS)
    #settingsDictionary2 = _applyToAllValuesInDictionary(settingsDictionary1, unicode.strip)
    return settingsDictionary1


def loadSettingsFromFileOrUseEmptySettings():
    """Load the settings dictionary using pickle module."""
    
    try:
        settingsFilename = getSettingsFilename()
        #_createFullDirectoryPathForFile(settingsFilename)  # JH: Why? If the file exists, the directory does too. If not, there is no reason to make it here. It will be made when saving. Therefore commented out.
        with open(settingsFilename, "rb") as settingsFileHandle:
            settingsRead = pickle.load(settingsFileHandle)
        settings = _cleanSettings(settingsRead)
    except:
        # Be silent about any errors while loading the settings.
        # An error could occur because there are no settings yet, but it 
        # could also have other reasons.
        # JH: Should maybe be more specific about which exceptions are being caught.
        settings = getEmptySettings()
    
    return settings
